package com.bigdata.service.impl;

import com.bigdata.dao.PmpMapper;
import com.bigdata.entity.dto.PhoneFlowPieDTO;
import com.bigdata.entity.pojo.*;
import com.bigdata.entity.vo.NwrVO;
import com.bigdata.entity.vo.PhoneFlowPieVO;
import com.bigdata.entity.vo.PhoneFlowRankVO;
import com.bigdata.service.PmpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigInteger;
import java.util.*;

@Service
public class PmpServiceImpl implements PmpService {

    @Autowired
    private PmpMapper pmpMapper;

    @Override
    public List<PopularMobilePhones> getPopularMobilePhones() {
        return this.pmpMapper.selectPopularMobilePhones();
    }

    // 22
    @Override
    public Object getPmpTrafficLocation() {
        // 获取原始数据列表
        List<PmpTrafficLocation> locations = this.pmpMapper.selectPmpTrafficLocation(20000000, 20200000);

        // Todo
        // 初始化目标数据结构，按公司型号分类
        Map<String, List<Map<String, Object>>> result = new HashMap<>();

        // 遍历原始数据，将数据按公司型号分类
        for (PmpTrafficLocation location : locations) {
            String companyModel = location.getCompanyModel();  // 公司型号

            // 处理经纬度数据，防止无效数据
            Double longitude = parseCoordinate(location.getUserLon());  // 经度
            Double latitude = parseCoordinate(location.getUserLat());  // 纬度

            Long heat = location.getHeat();  // 热度

            // 构建单条数据
            Map<String, Object> data = new HashMap<>();
            data.put("coord", new Double[]{longitude, latitude});
            data.put("value", heat);

            // 将数据添加到相应的公司型号中
            if (!result.containsKey(companyModel)) {
                result.put(companyModel, new ArrayList<>());
            }
            result.get(companyModel).add(data);
        }

        // 返回最终的格式化数据
        return result;
    }

    // 解析经纬度坐标的辅助方法
    private Double parseCoordinate(String coordinate) {
        try {
            // 先去除可能的空格和无效字符，然后转换为 Double
            if (coordinate != null && !coordinate.trim().isEmpty()) {
                String[] parts = coordinate.split(" ");  // 如果有空格，分割
                if (parts.length == 1) {
                    return Double.parseDouble(parts[0]);
                } else {
                    // 如果是 "0 -0.0" 这种格式，返回有效部分
                    return Double.parseDouble(parts[0]);  // 只取第一个有效数字
                }
            }
        } catch (NumberFormatException e) {
            // 捕获无效格式，返回一个默认值（比如 0.0）
            return 0.0;
        }
        return 0.0;
    }


    @Override
    public NwrVO getPmpNetworkQualityRanking() {
        // 获取原始数据列表
        List<PmpNetworkQualityRanking> list = this.pmpMapper.selectPmpNetworkQualityRanking();

        Set<String> legendsSet = new HashSet<>();  // 网络运营商有多少种
        Set<String> xAxisDataSet = new HashSet<>(); // 手机型号有多少种

        // 创建映射，记录每个网络运营商和手机型号的speed值
        Map<String, Map<String, List<Double>>> speedMap = new HashMap<>();

        for (PmpNetworkQualityRanking ranking : list) {
            String nwoperater = ranking.getNwoperater();
            String companyModel = ranking.getCompanyModel();
            double speed = ranking.getSpeed();

            legendsSet.add(nwoperater);
            xAxisDataSet.add(companyModel);

            // 初始化speedMap
            speedMap
                    .computeIfAbsent(nwoperater, k -> new HashMap<>())
                    .computeIfAbsent(companyModel, k -> new ArrayList<>())
                    .add(speed);
        }

// 将Set转为List
        List<String> legends = new ArrayList<>(legendsSet);
        List<String> xAxisData = new ArrayList<>(xAxisDataSet);

// 在第二个属性列表中增加 "all"
        legends.add("all");

// 创建二维数组，行数是legends的大小，列数是xAxisData的大小
        double[][] seriesData = new double[legends.size()][xAxisData.size()];

// 创建索引映射，用于查找网络运营商和手机型号对应的行列位置
        Map<String, Integer> legendsIndex = new HashMap<>();
        Map<String, Integer> xAxisDataIndex = new HashMap<>();

        for (int i = 0; i < legends.size(); i++) {
            legendsIndex.put(legends.get(i), i);
        }
        for (int i = 0; i < xAxisData.size(); i++) {
            xAxisDataIndex.put(xAxisData.get(i), i);
        }

// 计算"all"对应的平均值
        Map<String, Double> legendsAverageMap = new HashMap<>();
        for (String legend : legendsSet) {
            for (String model : xAxisDataSet) {
                // 获取该网络运营商和手机型号对应的所有speed值
                List<Double> speeds = speedMap.getOrDefault(legend, new HashMap<>()).getOrDefault(model, new ArrayList<>());
                if (!speeds.isEmpty()) {
                    double avgSpeed = speeds.stream().mapToDouble(Double::doubleValue).average().orElse(0);
                    // 填充二维数组
                    int row = legendsIndex.get(legend);
                    int col = xAxisDataIndex.get(model);
                    seriesData[row][col] = avgSpeed;
                }
            }
        }

// 填充"all"行：表示所有网络运营商的所有手机型号的平均值
        int allRowIndex = legendsIndex.get("all");
        for (int col = 0; col < xAxisData.size(); col++) {
            // 计算该手机型号的所有网络运营商的平均值
            double avgSpeedForAll = 0;
            int count = 0;
            for (String legend : legendsSet) {
                List<Double> speeds = speedMap.getOrDefault(legend, new HashMap<>()).getOrDefault(xAxisData.get(col), new ArrayList<>());
                if (!speeds.isEmpty()) {
                    avgSpeedForAll += speeds.stream().mapToDouble(Double::doubleValue).average().orElse(0);
                    count++;
                }
            }
            if (count > 0) {
                avgSpeedForAll /= count; // 平均所有运营商
            }
            seriesData[allRowIndex][col] = avgSpeedForAll;
        }

// 返回最终的结果
        return new NwrVO(legends, xAxisData, seriesData);

    }

    // 24.1
    @Override
    public PhoneFlowRankVO getPmpTrafficRankingFlow() {
        // 获取原始数据列表
        List<PmpTrafficRanking> rankings = this.pmpMapper.selectPmpTrafficRanking();

        // 创建 dimensions（维度）数组，包含固定的字段
        List<String> dimensions1 = new ArrayList<>();
        dimensions1.add("product");
        dimensions1.add("all");
        dimensions1.add("2G");
        dimensions1.add("3G");

        // 创建 source（数据源）二维数组
        List<List<Object>> source = new ArrayList<>();

        // 使用一个 Map 来存储每个手机型号对应的 2G 和 3G 流量
        Map<String, Map<String, Long>> modelTraffic = new HashMap<>();

        // 遍历排名数据，按手机型号和网络制式分别存储流量
        for (PmpTrafficRanking ranking : rankings) {
            String model = ranking.getCompanyModel();
            String networkType = ranking.getNetworkType();
            long speed = ranking.getSpeed().longValue(); // 将 BigInteger 转换为 long 类型

            // 初始化模型数据
            modelTraffic.putIfAbsent(model, new HashMap<>());
            Map<String, Long> traffic = modelTraffic.get(model);

            // 累加 2G 或 3G 流量
            traffic.put(networkType, traffic.getOrDefault(networkType, 0L) + speed);
        }

        // 按照模型数据填充 source 数据
        for (Map.Entry<String, Map<String, Long>> entry : modelTraffic.entrySet()) {
            String model = entry.getKey();
            Map<String, Long> traffic = entry.getValue();

            // 获取 2G 和 3G 流量，默认是 0
            long speed2G = traffic.getOrDefault("2G", 0L);
            long speed3G = traffic.getOrDefault("3G", 0L);
            long allSpeed = speed2G + speed3G; // 计算总流量（all）

            // 创建该手机型号的流量数据行
            List<Object> row = new ArrayList<>();
            row.add(model);  // 手机型号
            row.add(allSpeed); // 总流量（all）
            row.add(speed2G); // 2G 流量
            row.add(speed3G); // 3G 流量

            // 将数据行添加到 source 中
            source.add(row);
        }

        // 添加第一行数据（包含 "product", "all", "2G", "3G"）
        List<Object> headerRow = new ArrayList<>();
        headerRow.add("product");
        headerRow.add("all");
        headerRow.add("2G");
        headerRow.add("3G");
        source.add(0, headerRow);  // 插入到第一行

        // 创建 dimensions（维度）数组，包含新的字段
        List<String> dimensions = new ArrayList<>();
        dimensions.add("手机型号");
        dimensions.add("总流量");
        dimensions.add("Wi-Fi");
        dimensions.add("移动数据");

        // 返回封装好的 TrafficRankingResponse 对象
        return new PhoneFlowRankVO(dimensions, source);
    }
    // 24.2
    @Override
    public Object getPmpTrafficRankingPie() {
        // 获取原始数据列表
        List<PmpTrafficRanking> rankings = this.pmpMapper.selectPmpTrafficRanking();

        // 创建一个列表来存放转换后的 Pie 数据
        List<PhoneFlowPieDTO> pieDataList = new ArrayList<>();

        // 将原始数据处理成所需格式
        for (PmpTrafficRanking ranking : rankings) {
            // 从 PmpTrafficRanking 获取 speed 和 companyModel
            BigInteger speed = ranking.getSpeed();
            String companyModel = ranking.getCompanyModel();

            // 创建一个 PhoneFlowPieDTO 对象，封装数据
            PhoneFlowPieDTO pieDTO = new PhoneFlowPieDTO(speed, companyModel);

            // 将该 PieDTO 添加到列表中
            pieDataList.add(pieDTO);
        }

        // 创建一个 PhoneFlowPieVO 对象来封装所有的 Pie 数据
        PhoneFlowPieVO responseData = new PhoneFlowPieVO();
        responseData.setPieData(pieDataList);

        return responseData;
    }

    // 25.1，有点太过复杂，可能有坑
    @Override
    public Object getPmpOSTrafficRankingRank() {
        // 获取原始数据列表
        List<PmpOSTrafficRanking> rankings = this.pmpMapper.selectPmpOSTrafficRanking();
        System.out.println(rankings);

        // TODO 将原始数据处理为所需格式
        // 初始化维度数据
        List<String> dimensions = Arrays.asList("操作系统", "总流量", "2G", "3G");

        // 初始化源数据列表
        List<List<Object>> source = new ArrayList<>();

        // 添加表头数据，代表产品名（ALL）和各个流量类别
        source.add(Arrays.asList("product", "ALL", "2G", "3G"));

        // 根据操作系统和版本进行分组处理
        Map<String, Map<String, Integer>> osDataMap = new HashMap<>();

        // 遍历原始数据，将数据按照操作系统和网络类型分类
        for (PmpOSTrafficRanking ranking : rankings) {
            String osVersion = ranking.getOsAndVersion(); // 操作系统版本
            String networkType = ranking.getNetworkType(); // 网络类型（Wi-Fi或移动数据）
            Integer speed = ranking.getSpeed().intValue(); // 网络速度（流量）

            // 初始化内层map
            osDataMap.putIfAbsent(osVersion, new HashMap<>());

            // 累加对应网络类型的数据
            if ("2G".equals(networkType)) {
                osDataMap.get(osVersion).put("2G", osDataMap.get(osVersion).getOrDefault("2G", 0) + speed);
            } else if ("3G".equals(networkType)) {
                osDataMap.get(osVersion).put("3G", osDataMap.get(osVersion).getOrDefault("3G", 0) + speed);
            }
        }

        // 构建 "ALL" 和操作系统具体数据
        for (Map.Entry<String, Map<String, Integer>> entry : osDataMap.entrySet()) {
            String osVersion = entry.getKey();
            Map<String, Integer> data = entry.getValue();

            // 计算总流量
            int totalTraffic = data.getOrDefault("2G", 0) + data.getOrDefault("3G", 0);

            // 添加数据到源列表
            source.add(Arrays.asList(osVersion, totalTraffic, data.getOrDefault("2G", 0),
                    data.getOrDefault("3G", 0)));
        }

        // 构建最终数据结果
        Map<String, Object> result = new HashMap<>();
        result.put("dimensions", dimensions);
        result.put("source", source);

        return result; // 返回最终的格式化数据
    }

    // 25.2 存疑
    @Override
    public Object getPmpOSTrafficRankingPie() {
        // 获取原始数据列表
        List<PmpOSTrafficRanking> rankings = this.pmpMapper.selectPmpOSTrafficRanking();

        // TODO 将原始数据处理为所需格式
        // 初始化一个map，用于存储每种操作系统的流量总和
        Map<String, Long> osTrafficMap = new HashMap<>();

        // 遍历原始数据，将数据按照操作系统进行分类
        for (PmpOSTrafficRanking ranking : rankings) {
            String osVersion = ranking.getOsAndVersion(); // 操作系统版本
            Long speed = ranking.getSpeed(); // 流量

            // 判断操作系统类型并进行分类累加
            if (osVersion.contains("android2.3.7")) {
                osTrafficMap.put("android2.3.7", osTrafficMap.getOrDefault("android2.3.7", 0L) + speed);
            } else if (osVersion.contains("android4.0.4")) {
                osTrafficMap.put("android4.0.4", osTrafficMap.getOrDefault("android4.0.4", 0L) + speed);
            } else if (osVersion.contains("android4.1.2")) {
                osTrafficMap.put("android4.1.2", osTrafficMap.getOrDefault("android4.1.2", 0L) + speed);
            } else if (osVersion.contains("android4.1.2")) {
                osTrafficMap.put("android4.3", osTrafficMap.getOrDefault("android4.3", 0L) + speed);
            } else {
                osTrafficMap.put("Others", osTrafficMap.getOrDefault("Others", 0L) + speed);
            }
        }

        // 构建饼图数据
        List<Map<String, Object>> pieData = new ArrayList<>();
        for (Map.Entry<String, Long> entry : osTrafficMap.entrySet()) {
            Map<String, Object> pieItem = new HashMap<>();
            pieItem.put("name", entry.getKey());
            pieItem.put("value", entry.getValue());
            pieData.add(pieItem);
        }

        // 返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("pieData", pieData);

        return result; // 返回饼图数据
    }

    // 26
    @Override
    public Object getPmpDistribution() {
        // 获取原始数据列表
        List<PmpDistribution> distributions = this.pmpMapper.selectPmpDistribution();

        // TODO 将原始数据处理为所需格式

        // 初始化目标数据列表
        List<Map<String, Object>> cities = new ArrayList<>();

        // 遍历原始数据，将数据转换为目标格式
        for (PmpDistribution distribution : distributions) {
            Map<String, Object> city = new HashMap<>();
            city.put("name", distribution.getCompanyModel()); // 手机型号名称
            city.put("longitude", distribution.getLongitude()); // 经度
            city.put("latitude", distribution.getLatitude()); // 纬度

            cities.add(city);
        }

        // 返回格式化后的数据
        Map<String, Object> result = new HashMap<>();
        result.put("cities", cities);

        return result; // 返回最终的城市数据
    }

    // 27
    @Override
    public Object getPmpOSDistribution() {
        // 获取原始数据列表
        List<PmpOSDistribution> distributions = this.pmpMapper.selectPmpOSDistribution();

        // TODO 将原始数据处理为所需格式
        // 初始化目标数据列表
        List<Map<String, Object>> cities = new ArrayList<>();

        // 遍历原始数据，将数据转换为目标格式
        for (PmpOSDistribution distribution : distributions) {
            Map<String, Object> city = new HashMap<>();
            city.put("name", distribution.getOs()); // 操作系统名称
            city.put("value", distribution.getOsVersion()); // 操作系统版本
            city.put("longitude", distribution.getLongitude()); // 经度
            city.put("latitude", distribution.getLatitude()); // 纬度

            cities.add(city);
        }

        // 返回格式化后的数据
        Map<String, Object> result = new HashMap<>();
        result.put("cities", cities);

        return result; // 返回最终的城市数据
    }
}
